#pragma once

#include "../DirectX/DirectXBase.h"
#include "../GameEngine.h"
#include "../Utilities/BasicLoader.h"

ref class GameEngine;
ref class LightBase;
ref class PointLight;
ref class GlassShatterScreenMesh;

ref class GameRenderer : public DirectXBase
{
internal:
	GameRenderer();

	concurrency::task<void>		CreateGameDeviceResourcesAsync(_In_ GameEngine^ game);
	void						CreateGameDeviceResourcesFinalize();
	void						CreateGameDeviceResourcesLights();
	virtual void				Initialize(Windows::UI::Core::CoreWindow^ window, Windows::UI::Xaml::Controls::SwapChainBackgroundPanel^ panel, float dpi) override;
	virtual void                CreateWindowSizeDependentResources() override;
	virtual void				Render() override;

	BasicLoader^				Loader() { return m_loader; }

	void						ApplyBloom(bool apply);

private:
	void						UpdateLights();
	DirectX::XMFLOAT4X4			GenerateQuadMatrix(float destWidth, float destHeight);
	void                        RenderTexturedQuad(float destWidth, float destHeight, ID3D11ShaderResourceView* const* texture1, ID3D11ShaderResourceView* const* texture2 = nullptr, ID3D11PixelShader* pixelShader = nullptr, ID3D11SamplerState* sampleState = nullptr, DirectX::XMFLOAT4 tintColor = DirectX::XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f));
	void						DebugDrawTarget(ID3D11ShaderResourceView* const* texture);
	GameEngine^					m_game;
	BasicLoader^				m_loader;
	float						m_currentBloomThreshold;

	bool												m_gameResourcesLoaded;
	Microsoft::WRL::ComPtr<ID3D11SamplerState>          m_samplerLinear;
	Microsoft::WRL::ComPtr<ID3D11InputLayout>           m_vertexLayout;
	Microsoft::WRL::ComPtr<ID3D11InputLayout>           m_normalMapVertexLayout;
	Microsoft::WRL::ComPtr<ID3D11InputLayout>           m_drawTexturedQuadVertexLayout;
	Microsoft::WRL::ComPtr<ID3D11BlendState1>			m_blendStateAlpha;
	Microsoft::WRL::ComPtr<ID3D11BlendState1>           m_blendStateOpaque;
	Microsoft::WRL::ComPtr<ID3D11BlendState1>			m_blendStateAdditive;
	Microsoft::WRL::ComPtr<ID3D11RasterizerState>		m_rasterizerState;
	Microsoft::WRL::ComPtr<ID3D11DepthStencilState>		m_depthStencilState;
	Microsoft::WRL::ComPtr<ID3D11DepthStencilState>     m_depthStencilStateNone;

	// Constant Buffers
	Microsoft::WRL::ComPtr<ID3D11Buffer>                m_bloomExtractConstantBufferChangesEveryFrame;
	Microsoft::WRL::ComPtr<ID3D11Buffer>                m_bloomBlurHorizontalConstantBufferChangesEveryFrame;
	Microsoft::WRL::ComPtr<ID3D11Buffer>                m_bloomBlurVerticalConstantBufferChangesEveryFrame;
	Microsoft::WRL::ComPtr<ID3D11Buffer>                m_bloomCombineConstantBufferChangesEveryFrame;
	Microsoft::WRL::ComPtr<ID3D11Buffer>                m_drawTexturedQuadConstantBufferChangesEveryDraw;

	// Vertex Buffers and Index Buffers
	Microsoft::WRL::ComPtr<ID3D11Buffer>                m_drawTexturedQuadVertexBuffer;
	Microsoft::WRL::ComPtr<ID3D11Buffer>                m_drawTexturedQuadIndexBuffer;

	// Shaders
	Microsoft::WRL::ComPtr<ID3D11VertexShader>          m_drawTexturedQuadVertexShader;
	Microsoft::WRL::ComPtr<ID3D11PixelShader>           m_drawTexturedQuadPixelShader;
	Microsoft::WRL::ComPtr<ID3D11PixelShader>           m_bloomExtractPixelShader;
	Microsoft::WRL::ComPtr<ID3D11PixelShader>           m_bloomBlurPixelShader;
	Microsoft::WRL::ComPtr<ID3D11PixelShader>           m_bloomCombinePixelShader;

	// Render Targets
	RenderTarget^                                       m_mainRenderTarget;
	RenderTarget^                                       m_bloomRenderTargetOne;
	RenderTarget^                                       m_bloomRenderTargetTwo;

	// Textures
	Microsoft::WRL::ComPtr<ID3D11ShaderResourceView>    m_C4FTexture;
	Microsoft::WRL::ComPtr<ID3D11ShaderResourceView>    m_TransparentTexture;
	Microsoft::WRL::ComPtr<ID3D11ShaderResourceView>    m_LinenTexture;
	Microsoft::WRL::ComPtr<ID3D11ShaderResourceView>    m_CracksTexture;
	Microsoft::WRL::ComPtr<ID3D11ShaderResourceView>    m_CracksNormalMapTexture;
	Microsoft::WRL::ComPtr<ID3D11ShaderResourceView>    m_CornerTexture;
	Microsoft::WRL::ComPtr<ID3D11ShaderResourceView>    m_CornerNormalMapTexture;
	Microsoft::WRL::ComPtr<ID3D11ShaderResourceView>	m_DamageTexture;
	Microsoft::WRL::ComPtr<ID3D11ShaderResourceView>	m_PaddleTexture;
	Microsoft::WRL::ComPtr<ID3D11ShaderResourceView>	m_GlassTexture;

	//
	// Deferred rendering pipeline
	//

	// Render Targets
	RenderTarget^										m_lightPrePassPositionBufferRenderTarget;
	RenderTarget^										m_lightPrePassNormalBufferRenderTarget;
	RenderTarget^										m_lightPassLightBufferRenderTarget;

	Microsoft::WRL::ComPtr<ID3D11SamplerState>			m_samplerPoint;

	Microsoft::WRL::ComPtr<ID3D11VertexShader>			m_lightPrePassVertexShader;
	Microsoft::WRL::ComPtr<ID3D11VertexShader>			m_lightPrePassNormalMapVertexShader;
	Microsoft::WRL::ComPtr<ID3D11PixelShader>			m_lightPrePassPixelShader;
	Microsoft::WRL::ComPtr<ID3D11PixelShader>			m_lightPrePassNormalMapPixelShader;
	Microsoft::WRL::ComPtr<ID3D11Buffer>				m_lightPrePassOnWindowSizeChangeBuffer;
	Microsoft::WRL::ComPtr<ID3D11Buffer>				m_lightPrePassPerFrameBuffer;
	Microsoft::WRL::ComPtr<ID3D11Buffer>				m_lightPrePassPerMeshBuffer;

	Microsoft::WRL::ComPtr<ID3D11VertexShader>			m_lightPassVertexShader;
	Microsoft::WRL::ComPtr<ID3D11PixelShader>			m_lightPassPointLightPixelShader;
	Microsoft::WRL::ComPtr<ID3D11Buffer>				m_lightPassOnWindowSizeChangeBuffer;
	Microsoft::WRL::ComPtr<ID3D11Buffer>				m_lightPassLightParametersBuffer;
	Microsoft::WRL::ComPtr<ID3D11Buffer>				m_lightPassViewParametersBuffer;
	Microsoft::WRL::ComPtr<ID3D11Buffer>				m_lightPassPointLightDetailsBuffer;

	Microsoft::WRL::ComPtr<ID3D11VertexShader>			m_lightFinalPassVertexShader;
	Microsoft::WRL::ComPtr<ID3D11PixelShader>			m_lightFinalPassPixelShader;
	Microsoft::WRL::ComPtr<ID3D11Buffer>				m_lightFinalPassOnWindowSizeChangeBuffer;
	Microsoft::WRL::ComPtr<ID3D11Buffer>				m_lightFinalPassPerFrameBuffer;
	Microsoft::WRL::ComPtr<ID3D11Buffer>				m_lightFinalPassPerMeshBuffer;

	std::vector<LightBase^>								m_allLights;
	std::vector<PointLight^>							m_pointLights;

	bool												m_applyBloom;

	GlassShatterScreenMesh^								m_glassShatterScreenMesh;
	bool												m_glassShatterScreenIsRunning;
	Microsoft::WRL::ComPtr<ID3D11RasterizerState>		m_rasterizerStateCullModeNone;
	Microsoft::WRL::ComPtr<ID3D11Buffer>				m_glassShatterVertexBuffer;
	Microsoft::WRL::ComPtr<ID3D11VertexShader>			m_glassShatterVertexShader;
	Microsoft::WRL::ComPtr<ID3D11GeometryShader>		m_glassShatterGeometryShader;
	Microsoft::WRL::ComPtr<ID3D11InputLayout>			m_glassShatterVertexLayout;
	Microsoft::WRL::ComPtr<ID3D11PixelShader>			m_glassShatterPixelShader;
	Microsoft::WRL::ComPtr<ID3D11Buffer>				m_glassShatterOnWindowSizeChangeBuffer;
	Microsoft::WRL::ComPtr<ID3D11Buffer>				m_glassShatterPerFrameBuffer;
	Microsoft::WRL::ComPtr<ID3D11Buffer>				m_glassShatterPerMeshBuffer;
};
